#include <ean13.hpp>

#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/gil/extension/io/jpeg_io.hpp>

#include <iostream>

using namespace boost::gil;

template < typename P >
struct ean13_fn
{
	typedef point2<ptrdiff_t>    point_t;

	typedef ean13_fn        const_t;
	typedef P                    value_type;
	typedef value_type           reference;
	typedef value_type           const_reference;
	typedef point_t              argument_type;
	typedef reference            result_type;
	BOOST_STATIC_CONSTANT(bool, is_mutable=false);

	ean13_fn()
	{
	}

	ean13_fn( const barcode::ean13& ean13_, const point_t& size_ )
		: _ean13_binary( ean13_ )
		, _img_size( size_ )
	{
	}

	result_type operator()( const point_t& point_ ) const
	{
		std::size_t bit_index_ = _ean13_binary.visible_bits_count() * point_.x / _img_size.x;
		return gray8_pixel_t( _ean13_binary.visible_bit_at( bit_index_ )? 0: 255 );
	}

private:
	barcode::ean13_binary _ean13_binary;
	point_t _img_size;

};

int main( int argc_, char* argv_[] )
{
	if ( argc_ <= 1 )
	{
		std::cerr << "please enter barcode" << std::endl;
		return 1;
	}

	typedef ean13_fn<gray8_pixel_t> deref_t;
	typedef deref_t::point_t            point_t;
	typedef virtual_2d_locator<deref_t,false> locator_t;
	typedef image_view<locator_t> ean13_view_t;

	try
	{
		barcode::ean13 ean13_( argv_[ 1 ] );

		point_t dims( barcode::_ean13_bits_count, barcode::_ean13_bits_count / 2 );

		ean13_view_t ean13_view_( dims
			, locator_t(point_t(0,0), point_t(1,1), deref_t(ean13_, dims) )
			);

		jpeg_write_view( to_string( ean13_ ) + ".jpeg", ean13_view_ );
	}
	catch ( const std::runtime_error& e_ )
	{
		std::cerr << e_.what();
		return 1;
	}

	return 0;
}
